import { createId } from "@paralleldrive/cuid2";
import { useTranslate } from "@tolgee/react";
import type {
  Item,
  ItemIndices,
} from "@typebot.io/blocks-core/schemas/items/schema";
import type { CardsItem } from "@typebot.io/blocks-inputs/cards/schema";
import { Button } from "@typebot.io/ui/components/Button";
import { Popover } from "@typebot.io/ui/components/Popover";
import { Settings01Icon } from "@typebot.io/ui/icons/Settings01Icon";
import { cn } from "@typebot.io/ui/lib/cn";
import { cx } from "@typebot.io/ui/lib/cva";
import { useState } from "react";
import { ImageOrPlaceholder } from "@/components/ImageOrPlaceholder";
import { ImageUploadContent } from "@/components/ImageUploadContent/ImageUploadContent";
import {
  MultiLineEditable,
  type MultiLineEditableProps,
} from "@/components/MultiLineEditable";
import {
  SingleLineEditable,
  type SingleLineEditableProps,
} from "@/components/SingleLineEditable";
import {
  GhostableItem,
  StacksWithGhostableItems,
} from "@/components/StackWithGhostableItems";
import { useTypebot } from "@/features/editor/providers/TypebotProvider";
import { BlockSourceEndpoint } from "@/features/graph/components/endpoints/BlockSourceEndpoint";
import { PlaceholderNode } from "@/features/graph/components/nodes/PlaceholderNode";
import { useGraph } from "@/features/graph/providers/GraphProvider";
import { CardsItemSettings } from "./CardsItemSettings";

type Props = {
  item: CardsItem;
  indices: ItemIndices;
  isMouseOver: boolean;
  blockId: string;
  groupId: string;
};

export const CardsItemNode = ({
  item,
  indices,
  isMouseOver,
  blockId,
  groupId,
}: Props) => {
  const { t } = useTranslate();
  const { typebot } = useTypebot();
  const { updateItem, deleteItemPath } = useTypebot();
  const { openedNodeId, setOpenedNodeId } = useGraph();

  const updateTitle = (value: string | null | undefined) => {
    updateItem(indices, {
      title: value,
    } as Item);
  };

  const updateDescription = (value: string | null | undefined) => {
    updateItem(indices, {
      description: value,
    } as Item);
  };

  const updateItemSettings = (options: CardsItem["options"]) => {
    updateItem(indices, { ...item, options } as Item);
  };

  const updateImage = (url: string | null | undefined) => {
    updateItem(indices, { ...item, imageUrl: url } as Item);
  };

  const addPath = () => {
    updateItem(indices, {
      paths: [...(item.paths ?? []), { id: createId() }],
    } as Item);
  };

  const deletePath = (idx: number) => {
    deleteItemPath({
      ...indices,
      pathIndex: idx,
    });
  };

  const updatePathText = (idx: number, value: string) => {
    updateItem(indices, {
      paths: item.paths?.map((path, i) =>
        i === idx ? { ...path, text: value } : path,
      ),
    } as Item);
  };

  return (
    <Popover.Root
      isOpen={openedNodeId === item.id}
      onOpen={(event) => {
        if (event?.type === "click") return;
        setOpenedNodeId(item.id);
      }}
      onClose={() => setOpenedNodeId(undefined)}
    >
      <Popover.Trigger
        render={(props) => (
          <div className="flex flex-col gap-0 justify-center w-full" {...props}>
            <StacksWithGhostableItems gapPixel={8}>
              <GhostableItem
                ghostLabel="Add image"
                onGhostClick={() => {
                  updateImage(undefined);
                }}
              >
                {item.imageUrl !== null ? (
                  <Popover.Root
                    isOpen={
                      openedNodeId === `${item.id}-${indices.itemIndex}-image`
                    }
                    onOpen={() =>
                      setOpenedNodeId(`${item.id}-${indices.itemIndex}-image`)
                    }
                    onClose={() => setOpenedNodeId(undefined)}
                  >
                    <Popover.Trigger>
                      <ImageOrPlaceholder
                        className="w-full h-[110px] shrink-0 transition-filter rounded-md hover:brightness-95 rounded-b-none"
                        src={item.imageUrl ?? undefined}
                      />
                    </Popover.Trigger>
                    <Popover.Popup side="right" className="max-w-[400px]">
                      {typebot && (
                        <ImageUploadContent
                          uploadFileProps={{
                            workspaceId: typebot?.workspaceId,
                            typebotId: typebot?.id,
                            blockId: item.id,
                            itemId: item.id,
                          }}
                          defaultUrl={item.imageUrl ?? undefined}
                          onSubmit={(url) => {
                            updateImage(url);
                          }}
                          onDelete={() => {
                            updateImage(null);
                          }}
                          additionalTabs={{
                            giphy: true,
                            unsplash: true,
                          }}
                        />
                      )}
                    </Popover.Popup>
                  </Popover.Root>
                ) : null}
              </GhostableItem>
              <GhostableItem
                ghostLabel="Add title"
                onGhostClick={() => {
                  updateTitle(undefined);
                }}
                className="mx-2"
              >
                {item.title !== null ? (
                  <SingleLineDeletableEditable
                    className={cx(
                      "flex-1 text-sm font-semibold px-2",
                      item.description !== null && "-mb-2",
                    )}
                    defaultValue={item.title ?? "Title"}
                    defaultEdit={item.title === undefined}
                    onValueCommit={updateTitle}
                    onDelete={() => updateTitle(null)}
                  />
                ) : null}
              </GhostableItem>
              <GhostableItem
                ghostLabel="Add description"
                onGhostClick={() => {
                  updateDescription(undefined);
                }}
                className="mx-2"
              >
                {item.description !== null ? (
                  <MultiLineDeletableEditable
                    className={cx("flex-1 text-xs mb-2 px-2")}
                    defaultValue={item.description ?? "Description"}
                    defaultEdit={item.description === undefined}
                    onValueCommit={updateDescription}
                    onDelete={() => updateDescription(null)}
                  />
                ) : null}
              </GhostableItem>
            </StacksWithGhostableItems>

            <div className="flex flex-col gap-0 px-2">
              {item.paths?.map((path, idx) => (
                <SingleLineDeletableEditable
                  onDelete={() => deletePath(idx)}
                  key={path.id}
                  onValueCommit={(value) => updatePathText(idx, value)}
                  defaultValue={path.text ?? "Button"}
                  defaultEdit={path.text === undefined}
                  className={cn("relative")}
                  common={{
                    className: cn(
                      "justify-center text-center text-sm relative border-gray-6 rounded-none",
                      idx === 0 && "rounded-t-md border-b-0",
                      idx !== 0 && "border border-b-0",
                      idx === (item.paths?.length ?? 1) - 1 &&
                        "rounded-b-md border-b",
                    ),
                  }}
                >
                  <BlockSourceEndpoint
                    source={{
                      blockId,
                      itemId: item.id,
                      pathId: path.id,
                    }}
                    groupId={groupId}
                    className="absolute right-[-57px] bottom-[-2px] pointer-events-[all]"
                  />
                </SingleLineDeletableEditable>
              ))}
              <PlaceholderNode
                hitboxYExtensionPixels={5}
                expandedHeightPixels={30}
                initialPaddingPixel={0}
                expandedPaddingPixel={0}
                className="text-xs font-medium rounded-t-none"
                onClick={addPath}
              >
                Add button
              </PlaceholderNode>
            </div>

            {isMouseOver && (
              <div className="flex rounded-md bg-gray-1 absolute -right-1 -top-1 z-10 animate-in fade-in-0 slide-in-from-top-1 slide-in-from-right-1">
                <Button
                  aria-label={t("blocks.inputs.button.openSettings.ariaLabel")}
                  variant="ghost"
                  size="icon"
                  className="shadow-md size-7"
                  onClick={() => setOpenedNodeId(item.id)}
                >
                  <Settings01Icon />
                </Button>
              </div>
            )}
          </div>
        )}
      />
      <Popover.Popup side="right" className="p-4">
        <CardsItemSettings
          options={item.options}
          onSettingsChange={updateItemSettings}
        />
      </Popover.Popup>
    </Popover.Root>
  );
};

const SingleLineDeletableEditable = ({
  defaultValue,
  className,
  defaultEdit,
  children,
  preview,
  input,
  common,
  onValueCommit,
  onDelete,
}: Omit<SingleLineEditableProps, "value"> & {
  defaultValue: string;
  onDelete: () => void;
}) => {
  const [value, setValue] = useState(defaultValue);

  const handleKeyPress = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === "Backspace" && value === "") onDelete();
  };

  return (
    <SingleLineEditable
      className={className}
      value={value}
      defaultEdit={defaultEdit}
      input={{
        ...input,
        onValueChange: setValue,
        onKeyDownCapture: handleKeyPress,
      }}
      common={common}
      preview={preview}
      onValueCommit={() => onValueCommit(value)}
    >
      {children}
    </SingleLineEditable>
  );
};

const MultiLineDeletableEditable = ({
  defaultValue,
  className,
  defaultEdit,
  onValueCommit,
  onDelete,
}: Omit<MultiLineEditableProps, "value"> & {
  defaultValue: string;
  onDelete: () => void;
}) => {
  const [value, setValue] = useState(defaultValue);

  const handleKeyPress = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
    if (e.key === "Backspace" && value === "") onDelete();
  };

  return (
    <MultiLineEditable
      className={className}
      value={value}
      defaultEdit={defaultEdit}
      input={{
        onValueChange: setValue,
        onKeyDownCapture: handleKeyPress,
      }}
      onValueCommit={() => onValueCommit(value)}
    />
  );
};
